package com.sp.intercepted;

import com.sp.exception.BusinessException;
import com.sp.properties.JWTProperties;
import com.sp.utils.EmployeeThreadLocal;
import com.sp.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static com.sp.constant.EmployeeMessageConstant.TOKEN_ERROR;

/**
 * jwt令牌校验的拦截器
 *
 * @author tong
 */
@Component
@Slf4j
public class JwtTokenInterceptor implements HandlerInterceptor {

    @Autowired
    private JWTProperties jwtProperties;

    /**
     * 校验jwt
     */
    @Override
    public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {
        // 判断当前拦截到的是Controller的方法还是其他资源
        // springmvc启动时候，扫描所有controller类，解析所有映射方法将每个映射方法封装一个对象HandlerMethod，
        // 该类包含所有请求映射方法信息（映射路径、方法名、参数、注解、返回值）
        if (!(handler instanceof HandlerMethod)) {
            //当前拦截到的不是动态方法，直接放行
            return true;
        }

        //从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getTokenName());
        //校验令牌
        try {
            //过期将解析失败，报错
            Claims claims = JwtUtil.parseJWT(jwtProperties.getSecretKey(), token);
            EmployeeThreadLocal.setEmployee((Integer) claims.get("id"), (String) claims.get("name"));

            //通过，放行
            return true;
        } catch (Exception e) {
            //不通过，响应401状态码，生成的token已经过期
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            throw new BusinessException(TOKEN_ERROR);
        }
    }

    @Override
    public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) {
        EmployeeThreadLocal.removeEmployee();
    }

}
